package controll

import (
	"encoding/json"
	"fmt"
	"haodayizhi/global"
	"haodayizhi/model"
	mtype "haodayizhi/types"
	util "haodayizhi/utils"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

// 获取用户信息
func UserInfoHandler(c *gin.Context) {
	var tokenConfig mtype.TokenConfig
	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "获取成功",
	}
	userModel := model.User{}
	id, ok := c.GetQuery("id")
	nId, err := strconv.Atoi(id)

	// 如果存在查询参数id，则获取指定用户信息
	if ok && nId > 0 {
		if err != nil {
			util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user info: %v", err))
			util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, response, err)
			return
		}
		userInfo, err := userModel.GetUserByID(int64(nId))
		if err == nil {
			util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user info: %v", err))
			util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, response, err)
			return
		}
		response.Result = userInfo
		c.JSON(http.StatusOK, response)
		return
	}
	// 获取用户信息
	headInfo, exists := c.Get(global.LOG_USER)
	headInfoByte, err := json.Marshal(headInfo)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user info: %v", err))
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, response, err)
		return
	}
	err = json.Unmarshal(headInfoByte, &tokenConfig)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user info: %v", err))
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, response, err)
		return
	}
	if !exists {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user info: %v", exists))
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, response, err)
		return
	}
	reuslt, err := userModel.GetUserByID(tokenConfig.UserID)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user info: %v", err))
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, response, err)
		return
	}

	authlist, err := GetUserAuth(tokenConfig.UserID)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user info: %v", err))
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, response, err)
		return
	}

	filtterData := map[string]interface{}{
		"id":        reuslt.ID,
		"username":  reuslt.Username,
		"age":       reuslt.Age,
		"birth":     reuslt.Birth,
		"gender":    reuslt.Gender,
		"signature": reuslt.Signature,
		"email":     reuslt.Email,
		"cellphone": reuslt.Cellphone,
		"avatarUrl": reuslt.AvatarURL,
		"createdAt": reuslt.CreatedAt,
		"isRemoved": reuslt.IsRemoved,
		"auth":      authlist,
	}
	response.Result = filtterData
	c.JSON(http.StatusOK, response)
}

// 修改用户信息
func ChangeUserInfoHandler(c *gin.Context) {
	var tokenConfig mtype.TokenConfig
	user := &model.User{}
	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "修改成功",
	}
	// Construct avatar file paths
	// 获取用户信息
	headInfo, exists := c.Get(global.LOG_USER)
	headInfoByte, err := json.Marshal(headInfo)
	if err != nil {
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, nil, err)
		return
	}
	err = json.Unmarshal(headInfoByte, &tokenConfig)
	if err != nil {
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, nil, err)
		return
	}
	if !exists {
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, nil, err)
		return
	}
	// 获取用户信息
	reuslt, err := user.GetUserByID(tokenConfig.UserID)
	if err != nil {
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, nil, err)
		return
	}

	// 获取用户的请求信息
	err = c.ShouldBindJSON(&user)
	if err != nil {
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, nil, err)
		return
	}

	now := time.Now()
	// 修改用户信息
	reuslt.Username = user.Username
	reuslt.Age = user.Age

	reuslt.Birth = user.Birth
	reuslt.Gender = user.Gender
	reuslt.Signature = user.Signature
	reuslt.Email = user.Email
	reuslt.Cellphone = user.Cellphone
	reuslt.UpdatedAt = &now
	err = user.UpdateUser()
	if err != nil {
		util.CommonErrorHandler(c, "Failed to get user info", http.StatusInternalServerError, nil, err)
		return
	}
	response.Result = model.ConvertUserToResponse(*reuslt)
	c.JSON(http.StatusOK, response)
}

// 上传头像图片
// const (
// 	allowedExt = ".jpg" // List more allowed extensions if needed
// )

// UploadAvatar handles the avatar image upload.
func UploadAvatar(c *gin.Context) {
	idStr := c.Query("id")
	id, err := strconv.Atoi(idStr)
	if err != nil || id <= 0 {
		util.CommonErrorHandler(c, "Invalid user ID", http.StatusBadRequest, nil, err)
		return
	}

	user := &model.User{}
	userInfo, err := user.GetUserByID(int64(id))
	if err != nil {
		util.CommonErrorHandler(c, "Error retrieving user info:", http.StatusBadRequest, nil, err)
		return
	}

	file, err := c.FormFile("file")
	if err != nil {
		util.CommonErrorHandler(c, "Error retrieving avatar file:", http.StatusBadRequest, nil, err)
		return
	}

	rootDir, err := util.GetRootDir()
	if err != nil {
		util.CommonErrorHandler(c, "Error getting root directory:", http.StatusInternalServerError, nil, err)
		return
	}

	// Construct the path for the asset directory outside the bin directory
	avatarBaseDir := filepath.Join(rootDir, "asset/static/users_avatar_jpg/")
	avatarDir := filepath.Join(avatarBaseDir, userInfo.Email)
	avatarFile := filepath.Join(avatarDir, userInfo.Email+".jpg")

	if err := EnsureDirExists(avatarDir); err != nil {
		util.CommonErrorHandler(c, "Error creating directory:", http.StatusInternalServerError, nil, err)
		return
	}

	if err := c.SaveUploadedFile(file, avatarFile); err != nil {
		util.CommonErrorHandler(c, "Error saving avatar image:", http.StatusInternalServerError, nil, err)
		return
	}

	avatarUrl := fmt.Sprintf("%s/asset/static/users_avatar_jpg/%s/%s.jpg", GetDomain(), userInfo.Email, userInfo.Email)

	userInfo.AvatarURL = avatarUrl
	if err := user.UpdateUser(); err != nil {
		util.CommonErrorHandler(c, "Error updating user avatar URL:", http.StatusInternalServerError, nil, err)
		return
	}

	c.JSON(http.StatusOK, mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "Avatar uploaded successfully",
	})
}

func EnsureDirExists(dir string) error {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		return os.MkdirAll(dir, os.ModePerm)
	}
	return nil
}

func GetDomain() string {
	return global.Config.Front.Host + ":" + global.Config.Front.Port
}

// 获取用户列表
func GetUserList(c *gin.Context) {
	params := mtype.UserListParam{}
	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "Get user list successfully",
	}
	err := c.ShouldBindQuery(&params)
	if err != nil {
		util.CommonErrorHandler(c, "Error parsing query parameters:", http.StatusBadRequest, nil, err)
		return
	}
	users, total, err := model.GetUserList(params.Page, params.Limit)
	if err != nil {
		util.CommonErrorHandler(c, "Error retrieving user info:", http.StatusBadRequest, nil, err)
		return
	}
	response.Result = mtype.UserList{
		Total: total,
		List:  users,
	}
	c.JSON(http.StatusOK, response)
}

// 发送登录邮件
func SendLoginEmail(c *gin.Context) {
	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "发送成功",
	}
	var loginEmailParams struct {
		Email     string `json:"email" form:"email"`
		CellPhone string `json:"cellphone" form:"cellphone"`
		Mode      string `json:"mode" form:"mode"`
	}

	if err := c.ShouldBindJSON(&loginEmailParams); err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Invalid input: %v", err))
		util.CommonErrorHandler(c, "Invalid input", http.StatusBadRequest, nil, err)
		return
	}

	// 如果email和cellphone同时为空 返回错误
	if loginEmailParams.Email == "" && loginEmailParams.CellPhone == "" {
		util.CommonErrorHandler(c, "Invalid input", http.StatusBadRequest, nil, nil)
		return
	}
	if loginEmailParams.Mode != "register" && loginEmailParams.Mode != "login" {
		util.CommonErrorHandler(c, "Invalid input", http.StatusBadRequest, nil, nil)
		return
	}

	var result interface{}
	var err error
	if loginEmailParams.Mode == "register" {
		// 查询用户是否存在
		result, err = util.GetRegisterCodeValue(loginEmailParams.Email)

	} else {
		result, err = util.GetLoginCodeValue(loginEmailParams.Email)

	}

	// 如果上一个请求已经发送过验证码，则不能再次发送
	if err != nil {
		util.CommonErrorHandler(c, err.Error(), http.StatusBadRequest, nil, err)
		return
	}
	if result != nil {
		util.CommonErrorHandler(c, "该邮箱已有验证码，请1分钟后再试", http.StatusBadRequest, nil, nil)
		return
	}

	// 如果email 存在就是用emial 发送邮件

	if loginEmailParams.Email != "" && loginEmailParams.CellPhone == "" {
		// 查询用户是否存在
		if loginEmailParams.Mode == "login" {
			_, err := model.GetUserByEmail(loginEmailParams.Email)
			if err != nil {
				util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user by email: %v", err))
				util.CommonErrorHandler(c, "该邮箱未注册", http.StatusInternalServerError, nil, err)
				return
			}
		}
		code := util.GetEmailCode()
		var params map[string]interface{}
		if loginEmailParams.Mode == "register" {
			params = map[string]interface{}{
				"Title":   "注册验证码",
				"Heading": "你正在通过邮箱验证，请输入以下验证码，以完成登录操作。",
				"Content": "请在1分钟内输入验证码，以完成注册操作。",
				"code":    code,
				"Footer":  "如果你没有请求注册验证，请忽略此邮件。",
			}
		} else {
			params = map[string]interface{}{
				"Title":   "登录验证码",
				"Heading": "你正在通过邮箱验证登录你的好大一只系统，请输入以下验证码，以完成登录操作。",
				"Content": "请在1分钟内输入验证码，以完成登录操作。",
				"code":    code,
				"Footer":  "如果你没有请求登录验证，请忽略此邮件。",
			}
		}

		emailSendContent := mtype.EmailSendContent{
			From:         "好大一只",
			To:           []string{loginEmailParams.Email},
			Subject:      "DHH验证码",
			Template:     "/email/template/code_email.html",
			TemplateData: params,
		}
		err = util.SendEmail(emailSendContent)
		if err != nil {
			util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to send email: %v", err))
			util.CommonErrorHandler(c, "Failed to send email", http.StatusInternalServerError, nil, err)
			return
		}
		if loginEmailParams.Mode == "register" {
			// 保存验证码
			err = util.SetRegisterCodeValueToRedis(loginEmailParams.Email, code)
			if err != nil {
				util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to set code value: %v", err))
				util.CommonErrorHandler(c, "Failed to set code value", http.StatusInternalServerError, nil, err)
				return
			}
		} else {
			// 保存验证码
			err = util.SetLoginCodeValueToRedis(loginEmailParams.Email, code)
			if err != nil {
				util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to set code value: %v", err))
				util.CommonErrorHandler(c, "Failed to set code value", http.StatusInternalServerError, nil, err)
				return
			}
		}
	}
	c.JSON(http.StatusOK, response)
}

// 根据关键词获取用户列表
func GetUserListInField(c *gin.Context) {

	var userListParam mtype.UserSearchParam

	reponse := mtype.ResponseType{
		Message: "查询成功",
		Code:    200,
		Result:  map[string]string{},
	}

	err := c.ShouldBindQuery(&userListParam)
	if err != nil {
		util.CommonErrorHandler(c, "参数错误", http.StatusBadRequest, nil, err)
		return
	}
	useModel := model.User{}
	filterUser, total, err := useModel.SearchUserOnlyIdAndEmail(userListParam.Page, userListParam.Limit, userListParam.Filed)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to search user: %v", err))
		util.CommonErrorHandler(c, "查询失败", http.StatusInternalServerError, nil, err)
		return
	}

	reponse.Result = map[string]interface{}{
		"list":  filterUser,
		"total": total,
	}
	c.JSON(http.StatusOK, reponse)
}
